#include <math.h>
#include <stdlib.h>
#include <pthread.h>

#include "Test.hh"

Test::Test()
{
	srand(time(NULL));
}

LinkedList<pthread_t>* Test::createThread(USNumber Num, TRoutine StartRoutine)
{
	return createThread(Num, StartRoutine, NULL);
}

LinkedList<pthread_t>* 
Test::createThread(USNumber Num, TRoutine StartRoutine, void* Param)
{
	ResultOf Result;
	pthread_t ThreadId;
	
	LinkedList<pthread_t>* Temp;
	LinkedList<pthread_t>* Root = NULL;
	
	for (USNumber LC = 0; LC < Num; LC++)
	{
		Result = pthread_create(&ThreadId, NULL, StartRoutine, Param);
		checkErrorWRNull(Result, "Fail pthread_create.");
		
		Temp = new LinkedList<pthread_t>((pthread_t*)ThreadId);
		if (Temp == NULL)
		{
			notifyError(Temp, "Fail memory allocation.");
			return NULL;
		}
		
		if (Root != NULL)
		{
			Result = Root->linkToLeft(Temp);
			checkErrorWRNull(Result, "Fail Root->linkToLeft.");
		}
		
		Root = Temp;
	}
	
	return Root;
}

ResultOf Test::destoryThread(LinkedList<pthread_t>* Root)
{
	if (Root == NULL)
	{
		notifyError(Root, "Bad parameter.");
		return RETURN_PARAM_ERROR;
	}
	
	ResultOf Result;
	LinkedList<pthread_t>* Temp;
	
	while (Root != NULL)
	{
		Result = pthread_join((pthread_t)Root->tellContainer(), NULL);
		checkErrorWR(Result, "Fail pthread_join.");
		
		Temp = Root;
		Root = Root->tellRightNode();
		
		delete Temp;
	}
	
	return RETURN_OK;
}

void Test::delay(USNumber MicroSec)
{
	Number Dealy;
	Dealy = (Number)genNormal(MicroSec, MicroSec / 10);
	if (Dealy > 0)
		usleep(Dealy);
}

double Test::genUniform()
{
	return (double)random() / (double)RAND_MAX;
}

double Test::genNormal(double Average, double StandDeviation)
{
	double Z = sqrt(-2.0 * log(genUniform())) * cos(2 * M_PI * genUniform());
	return Average + StandDeviation * Z;
}

double Test::genExp(double Lamda)
{
	return (-log(1.0 - genUniform()) / Lamda);
}
